import { SessionDAO } from '../dao/SessionDAO';
import { UserDAO } from '../dao/UserDAO';
import { SystemDAO } from '../dao/SystemDAO';
import { IUser } from '../models/user';
import { ISession, ISessionDocument } from '../models/session';
import { ISystem, ISystemDocument } from '../models/system';
import mongoose from 'mongoose';
import crypto from 'crypto';
import bcryptjs from 'bcryptjs';

/**
 * 认证服务类
 * 负责处理用户认证、会话管理、SSO登录等功能
 */
export class AuthService {
  private sessionDAO: SessionDAO;
  private userDAO: UserDAO;
  private systemDAO: SystemDAO;

  constructor() {
    this.sessionDAO = new SessionDAO();
    this.userDAO = new UserDAO();
    this.systemDAO = new SystemDAO();
  }

  /**
   * 用户登录
   * @param username 用户名
   * @param password 密码
   * @param systemCode 系统代码
   * @param rememberMe 是否记住登录
   * @returns 登录结果
   */
  async login(username: string, password: string, systemCode: string, rememberMe: boolean = false): Promise<{
    success: boolean;
    sessionId?: string;
    user?: IUser;
    permissions?: any[];
    message?: string;
  }> {
    try {
      // 验证系统
      const system = await this.systemDAO.findByCode(systemCode);
      if (!system) {
        return { success: false, message: '系统不存在' };
      }

      if (!system.canAccess()) {
        return { success: false, message: '系统暂时不可访问' };
      }

      // 验证用户
      const user = await this.userDAO.findByUsername(username);
      if (!user) {
        return { success: false, message: '用户名或密码错误' };
      }

      if (user.status !== 'active') {
        return { success: false, message: '用户账户已被禁用' };
      }

      // 验证密码
      const isPasswordValid = await bcryptjs.compare(password, user.password);
      if (!isPasswordValid) {
        return { success: false, message: '用户名或密码错误' };
      }

      // 创建会话
      const sessionId = this.generateSessionId();
      const expiresAt = new Date(Date.now() + (rememberMe ? 30 * 24 * 60 * 60 * 1000 : 24 * 60 * 60 * 1000));
      
      const sessionData = {
         sessionId,
         userId: user._id as mongoose.Types.ObjectId,
         systemId: system._id as mongoose.Types.ObjectId,
         type: 'user' as const,
         isActive: true,
         expiresAt,
         lastAccessAt: new Date(),
         ipAddress: '',
         userAgent: ''
       };

       await this.sessionDAO.create(sessionData);

       return {
          success: true,
          sessionId,
          user,
          permissions: [] // TODO: 获取用户权限
        };
    } catch (error) {
      console.error('用户登录失败:', error);
      return { success: false, message: '登录失败，请稍后重试' };
    }
  }

  /**
   * 用户登出
   * @param sessionId 会话ID
   * @returns 登出结果
   */
  async logout(sessionId: string): Promise<{
    success: boolean;
    message?: string;
  }> {
    try {
      const session = await this.sessionDAO.findBySessionId(sessionId);
      if (session) {
        await this.sessionDAO.update(sessionId, { isActive: false });
      }
      return { success: true, message: '登出成功' };
    } catch (error) {
      console.error('用户登出失败:', error);
      return { success: false, message: '登出失败，请稍后重试' };
    }
  }

  /**
   * 管理员登出
   * @param sessionId 会话ID
   * @returns 登出结果
   */
  async adminLogout(sessionId: string): Promise<{
    success: boolean;
    message?: string;
  }> {
    try {
      const session = await this.sessionDAO.findBySessionId(sessionId);
      if (session) {
        await this.sessionDAO.update(sessionId, { isActive: false });
      }
      return { success: true, message: '管理员登出成功' };
    } catch (error) {
      console.error('管理员登出失败:', error);
      return { success: false, message: '管理员登出失败，请稍后重试' };
    }
  }

  /**
   * SSO登录 - 单点登录
   * @param systemCode 系统代码
   * @param username 用户名
   * @param password 密码
   * @param ipAddress 客户端IP地址
   * @param userAgent 用户代理
   * @returns 登录结果
   */
  async ssoLogin(systemCode: string, username: string, password: string, ipAddress: string, userAgent?: string): Promise<{
    success: boolean;
    sessionId?: string;
    user?: IUser;
    system?: ISystemDocument;
    message?: string;
  }> {
    try {
      // 验证系统是否存在且可用
      const system = await this.systemDAO.findByCode(systemCode);
      if (!system) {
        return { success: false, message: '系统不存在' };
      }

      if (!system.canAccess()) {
        return { success: false, message: '系统不可访问' };
      }

      // 验证用户凭据
      const user = await this.userDAO.findByUsername(username);
      if (!user) {
        return { success: false, message: '用户名或密码错误' };
      }

      if (user.status !== 'active') {
        return { success: false, message: '用户账户已被禁用' };
      }

      // 验证密码
      const isPasswordValid = await bcryptjs.compare(password, user.password);
      if (!isPasswordValid) {
        return { success: false, message: '用户名或密码错误' };
      }

      // 检查是否已经在目标系统有活跃会话
      const existingSessionsResult = await this.sessionDAO.findAll({
        userId: user._id as mongoose.Types.ObjectId,
        systemId: system._id as mongoose.Types.ObjectId,
        isActive: true
      });

      if (existingSessionsResult.sessions.length > 0) {
        // 返回现有会话
        const existingSession = existingSessionsResult.sessions[0];
        return {
          success: true,
          sessionId: existingSession.sessionId,
          user,
          system,
          message: 'SSO登录成功'
        };
      }
      
      // 为目标系统创建新的会话
      const newSessionId = this.generateSessionId();
      const newSession = await this.sessionDAO.create({
        sessionId: newSessionId,
        userId: user._id as mongoose.Types.ObjectId,
        systemId: system._id as mongoose.Types.ObjectId,
        ipAddress,
        userAgent,
        sessionType: 'master',
        loginTime: new Date(),
        expiresAt: new Date(Date.now() + 24 * 60 * 60 * 1000), // 24小时过期
        isActive: true,
        syncedSystems: [system._id as mongoose.Types.ObjectId]
      });

      // 更新用户最后登录信息
      await this.userDAO.update(user._id as mongoose.Types.ObjectId, {
        lastLoginAt: new Date(),
        lastLoginIp: ipAddress
      });

      // 更新系统最后活跃时间
      await system.updateLastActive();

      return {
        success: true,
        sessionId: newSession.sessionId,
        user: user,
        system: system,
        message: 'SSO登录成功'
      };
    } catch (error) {
      console.error('SSO登录失败:', error);
      return { success: false, message: '登录失败，请稍后重试' };
    }
  }

  /**
   * SSO单点登出
   * @param sessionId 会话ID
   * @returns 登出结果
   */
  async ssoLogout(sessionId: string): Promise<{
    success: boolean;
    message?: string;
  }> {
    try {
      const session = await this.sessionDAO.findBySessionId(sessionId);
      if (!session) {
        return { success: false, message: '会话不存在' };
      }

      if (!session.isActive) {
        return { success: false, message: '会话已失效' };
      }

      // 注销会话
      await this.sessionDAO.update(sessionId, { isActive: false });

      // 如果是主会话，需要同步注销所有关联系统的会话
      if (session.sessionType === 'master') {
        await this.sessionDAO.invalidateUserSessions(session.userId);
      }

      return { success: true };
    } catch (error) {
      console.error('SSO登出失败:', error);
      return { success: false, message: '登出失败，请稍后重试' };
    }
  }

  /**
   * 验证会话
   * @param sessionId 会话ID
   * @param systemCode 系统代码（可选）
   * @returns 验证结果
   */
  async verifySession(sessionId: string, systemCode?: string): Promise<{
    valid: boolean;
    session?: ISession;
    user?: IUser;
    system?: ISystemDocument;
    message?: string;
  }> {
    try {
      const session = await this.sessionDAO.findBySessionId(sessionId);
      if (!session) {
        return { valid: false, message: '会话不存在' };
      }

      if (!session.isActive) {
        return { valid: false, message: '会话已失效' };
      }

      if (session.isExpired()) {
        await this.sessionDAO.update(sessionId, { isActive: false });
        return { valid: false, message: '会话已过期' };
      }

      // 获取用户信息
      const user = await this.userDAO.findById(session.userId);
      if (!user || user.status !== 'active') {
        await this.sessionDAO.update(sessionId, { isActive: false });
        return { valid: false, message: '用户账户已被禁用' };
      }

      // 如果指定了系统代码，验证系统访问权限
      let system: ISystemDocument | null = null;
      if (systemCode) {
        system = await this.systemDAO.findByCode(systemCode);
        if (!system || system.status !== 'active') {
          return { valid: false, message: '系统不可访问' };
        }

        // 检查会话是否已同步到该系统
        if (session.sessionType === 'master' && !session.syncedSystems?.includes(system._id as mongoose.Types.ObjectId)) {
          // 自动同步会话到新系统
          await this.syncSession(sessionId, systemCode);
        }
      }

      // 更新会话最后访问时间
      await session.updateLastAccess();

      return {
        valid: true,
        session: session,
        user: user,
        system: system || undefined
      };
    } catch (error) {
      console.error('会话验证失败:', error);
      return { valid: false, message: '会话验证失败' };
    }
  }

  /**
   * 同步会话到指定系统
   * @param sessionId 会话ID
   * @param systemCode 目标系统代码
   * @returns 同步结果
   */
  async syncSession(sessionId: string, systemCode: string): Promise<{
    success: boolean;
    message?: string;
  }> {
    try {
      const session = await this.sessionDAO.findBySessionId(sessionId);
      if (!session || !session.isActive) {
        return { success: false, message: '会话不存在或已失效' };
      }

      const system = await this.systemDAO.findByCode(systemCode);
      if (!system || !system.canAccess()) {
        return { success: false, message: '目标系统不可访问' };
      }

      // 检查是否已经同步
      if (session.syncedSystems?.includes(system._id as mongoose.Types.ObjectId)) {
        return { success: true, message: '会话已同步到该系统' };
      }

      // 添加系统到同步列表
      await this.sessionDAO.addSyncedSystem(sessionId, system._id as mongoose.Types.ObjectId);

      // 更新系统最后活跃时间
      await system.updateLastActive();

      return { success: true };
    } catch (error) {
      console.error('会话同步失败:', error);
      return { success: false, message: '会话同步失败' };
    }
  }

  /**
   * 超级管理员登录
   * @param username 用户名
   * @param password 密码
   * @param ipAddress 客户端IP地址
   * @param userAgent 用户代理
   * @returns 登录结果
   */
  async superAdminLogin(username: string, password: string, ipAddress: string, userAgent?: string): Promise<{
    success: boolean;
    sessionId?: string;
    user?: IUser;
    message?: string;
  }> {
    try {
      // 验证是否为超级管理员账户
      if (username !== 'superadmin') {
        return { success: false, message: '权限不足，非超级管理员' };
      }

      // 从环境变量获取超级管理员密码
      const superAdminPassword = process.env.SUPER_ADMIN_PASSWORD;
      if (!superAdminPassword) {
        return { success: false, message: '系统配置错误' };
      }

      // 验证密码
      if (password !== superAdminPassword) {
        return { success: false, message: '用户名或密码错误' };
      }

      // 创建超级管理员会话
      const sessionId = this.generateSessionId();
      const session = await this.sessionDAO.create({
        sessionId,
        userId: new mongoose.Types.ObjectId(), // 虚拟用户ID
        ipAddress,
        userAgent,
        sessionType: 'master',
        loginTime: new Date(),
        expiresAt: new Date(Date.now() + 8 * 60 * 60 * 1000), // 8小时过期
        isActive: true
      });

      // 创建虚拟超级管理员用户对象
      const superAdminUser = {
        _id: session.userId,
        username: 'superadmin',
        email: 'superadmin@system.local',
        realName: '超级管理员',
        status: 'active'
      } as IUser;

      return {
        success: true,
        sessionId: session.sessionId,
        user: superAdminUser
      };
    } catch (error) {
      console.error('超级管理员登录失败:', error);
      return { success: false, message: '登录失败，请稍后重试' };
    }
  }

  /**
   * 管理员登录
   * @param username 用户名
   * @param password 密码
   * @param ipAddress 客户端IP地址
   * @param userAgent 用户代理
   * @returns 登录结果
   */
  async adminLogin(username: string, password: string, ipAddress: string, userAgent?: string): Promise<{
    success: boolean;
    sessionId?: string;
    user?: IUser;
    message?: string;
  }> {
    try {
      // 验证用户凭据
      const user = await this.userDAO.findByUsername(username);
      if (!user) {
        return { success: false, message: '用户名或密码错误' };
      }

      if (user.status !== 'active') {
        return { success: false, message: '用户账户已被禁用' };
      }

      const isPasswordValid = await user.comparePassword(password);
      if (!isPasswordValid) {
        return { success: false, message: '用户名或密码错误' };
      }

      // 验证用户是否具有管理员权限
      if (!user.isSuperAdmin && user.adminLevel === 'user') {
        return { success: false, message: '权限不足，非管理员用户' };
      }

      // 创建管理员会话
      const sessionId = this.generateSessionId();
      const session = await this.sessionDAO.create({
        sessionId,
        userId: user._id as mongoose.Types.ObjectId,
        ipAddress,
        userAgent,
        sessionType: 'master',
        loginTime: new Date(),
        expiresAt: new Date(Date.now() + 8 * 60 * 60 * 1000), // 8小时过期
        isActive: true
      });

      // 更新用户最后登录信息
      await this.userDAO.update(user._id as mongoose.Types.ObjectId, {
        lastLoginAt: new Date(),
        lastLoginIp: ipAddress
      });

      return {
        success: true,
        sessionId: session.sessionId,
        user: user
      };
    } catch (error) {
      console.error('管理员登录失败:', error);
      return { success: false, message: '登录失败，请稍后重试' };
    }
  }

  /**
   * 检查登录状态
   * @param sessionId 会话ID
   * @returns 登录状态检查结果
   */
  async checkLoginStatus(sessionId: string): Promise<{
    valid: boolean;
    user?: IUser;
    session?: ISession;
    message?: string;
  }> {
    try {
      const session = await this.sessionDAO.findBySessionId(sessionId);
      if (!session) {
        return { valid: false, message: '会话不存在' };
      }

      if (!session.isActive) {
        return { valid: false, message: '会话已失效' };
      }

      if (session.isExpired()) {
        await this.sessionDAO.update(sessionId, { isActive: false });
        return { valid: false, message: '会话已过期' };
      }

      // 获取用户信息
      const user = await this.userDAO.findById(session.userId);
      if (!user || user.status !== 'active') {
        await this.sessionDAO.update(sessionId, { isActive: false });
        return { valid: false, message: '用户账户已被禁用' };
      }

      // 更新会话最后访问时间
      await session.updateLastAccess();

      return {
        valid: true,
        user: user,
        session: session
      };
    } catch (error) {
      console.error('登录状态检查失败:', error);
      return { valid: false, message: '登录状态检查失败' };
    }
  }

  /**
   * SSO验证接口（供子系统调用）
   * @param sessionId 会话ID
   * @param systemCode 系统代码
   * @returns SSO验证结果，验证失败时返回SSO登录页面地址
   */
  async verifySSOSession(sessionId: string, systemCode: string): Promise<{
    valid: boolean;
    user?: IUser;
    session?: ISession;
    system?: ISystemDocument;
    ssoLoginUrl?: string;
    message?: string;
  }> {
    try {
      // 验证系统是否存在
      const system = await this.systemDAO.findByCode(systemCode);
      if (!system) {
        return {
          valid: false,
          message: '系统不存在',
          ssoLoginUrl: process.env.SSO_LOGIN_URL || 'http://localhost:3000/sso/login'
        };
      }

      if (!system.canAccess()) {
         return {
           valid: false,
           message: '系统不可访问',
           ssoLoginUrl: process.env.SSO_LOGIN_URL || 'http://localhost:3000/sso/login'
         };
       }

       // 验证会话
       const session = await this.sessionDAO.findBySessionId(sessionId);
       if (!session) {
         return {
           valid: false,
           message: '会话不存在',
           ssoLoginUrl: process.env.SSO_LOGIN_URL || 'http://localhost:3000/sso/login'
         };
       }

       if (!session.isActive || session.isExpired()) {
         return {
           valid: false,
           message: '会话已过期',
           ssoLoginUrl: process.env.SSO_LOGIN_URL || 'http://localhost:3000/sso/login'
         };
       }

       // 获取用户信息
       const user = await this.userDAO.findById(session.userId);
       if (!user || user.status !== 'active') {
         return {
           valid: false,
           message: '用户账户已被禁用',
           ssoLoginUrl: process.env.SSO_LOGIN_URL || 'http://localhost:3000/sso/login'
         };
       }

      // 检查用户是否有访问该系统的权限
      // TODO: 这里可以添加更详细的权限检查逻辑

      // 更新会话最后访问时间
      await session.updateLastAccess();

      return {
        valid: true,
        user: user,
        session: session,
        system: system
      };
    } catch (error) {
      console.error('SSO验证失败:', error);
      return {
        valid: false,
        message: 'SSO验证失败',
        ssoLoginUrl: process.env.SSO_LOGIN_URL || 'http://localhost:3000/sso/login'
      };
    }
  }

  /**
   * 通过sessionId验证会话（用于跨系统会话验证）
   * @param sessionId 会话ID
   * @returns 验证结果
   */
  async verifySessionById(sessionId: string): Promise<{
    valid: boolean;
    session?: ISession;
    user?: IUser;
    system?: ISystemDocument;
    message?: string;
  }> {
    try {
      const session = await this.sessionDAO.findBySessionId(sessionId);
      if (!session) {
        return { valid: false, message: '会话不存在' };
      }

      if (!session.isActive) {
        return { valid: false, message: '会话已失效' };
      }

      if (session.isExpired()) {
        await this.sessionDAO.update(sessionId, { isActive: false });
        return { valid: false, message: '会话已过期' };
      }

      // 获取用户信息
      const user = await this.userDAO.findById(session.userId);
      if (!user || user.status !== 'active') {
        await this.sessionDAO.update(sessionId, { isActive: false });
        return { valid: false, message: '用户账户已被禁用' };
      }

      // 获取系统信息
      let system: ISystemDocument | undefined;
      if (session.systemId) {
        const foundSystem = await this.systemDAO.findById(session.systemId);
        if (foundSystem) {
          system = foundSystem;
        }
      }

      // 更新会话最后访问时间
      await session.updateLastAccess();

      return {
        valid: true,
        session: session,
        user: user,
        system: system
      };
    } catch (error) {
      console.error('会话验证失败:', error);
      return { valid: false, message: '会话验证失败' };
    }
  }

  /**
   * 检查管理员权限
   * @param sessionId 会话ID
   * @returns 管理员权限检查结果
   */
  async checkAdminPermission(sessionId: string): Promise<{
    valid: boolean;
    session?: ISession;
    user?: IUser;
    isSuperAdmin?: boolean;
    message?: string;
  }> {
    return this.verifyAdminSession(sessionId);
  }

  /**
   * 验证管理员会话
   * @param sessionId 会话ID
   * @returns 验证结果
   */
  async verifyAdminSession(sessionId: string): Promise<{
    valid: boolean;
    session?: ISession;
    user?: IUser;
    isSuperAdmin?: boolean;
    message?: string;
  }> {
    try {
      const session = await this.sessionDAO.findBySessionId(sessionId);
      if (!session) {
        return { valid: false, message: '会话不存在' };
      }

      if (!session.isActive) {
        return { valid: false, message: '会话已失效' };
      }

      if (session.isExpired()) {
        await this.sessionDAO.update(sessionId, { isActive: false });
        return { valid: false, message: '会话已过期' };
      }

      if (session.sessionType !== 'master') {
        return { valid: false, message: '非管理员会话' };
      }

      // 检查是否为超级管理员会话
      const isSuperAdmin = session.userId.toString() === session.userId.toString() &&
                          !await this.userDAO.findById(session.userId);

      let user: IUser | undefined;
      if (!isSuperAdmin) {
        const foundUser = await this.userDAO.findById(session.userId);
        if (!foundUser || foundUser.status !== 'active') {
          await this.sessionDAO.update(sessionId, { isActive: false });
          return { valid: false, message: '用户账户已被禁用' };
        }
        user = foundUser;
      } else {
        // 创建虚拟超级管理员用户对象
        user = {
          _id: session.userId,
          username: 'superadmin',
          email: 'superadmin@system.local',
          realName: '超级管理员',
          status: 'active'
        } as IUser;
      }

      // 更新会话最后访问时间
      await session.updateLastAccess();

      return {
        valid: true,
        session: session,
        user: user,
        isSuperAdmin: isSuperAdmin
      };
    } catch (error) {
      console.error('管理员会话验证失败:', error);
      return { valid: false, message: '会话验证失败' };
    }
  }

  /**
   * 清理过期会话
   * @returns 清理的会话数量
   */
  async cleanupExpiredSessions(): Promise<number> {
    try {
      return await this.sessionDAO.deleteExpired();
    } catch (error) {
      console.error('清理过期会话失败:', error);
      return 0;
    }
  }

  /**
   * 获取用户活跃会话
   * @param userId 用户ID
   * @returns 活跃会话列表
   */
  async getUserActiveSessions(userId: mongoose.Types.ObjectId): Promise<ISessionDocument[]> {
    try {
      return await this.sessionDAO.findByUserId(userId);
    } catch (error) {
      console.error('获取用户活跃会话失败:', error);
      return [];
    }
  }

  /**
   * 强制注销用户所有会话
   * @param userId 用户ID
   * @returns 操作结果
   */
  async forceLogoutUser(userId: mongoose.Types.ObjectId): Promise<{
    success: boolean;
    message?: string;
  }> {
    try {
      await this.sessionDAO.invalidateUserSessions(userId);
      return { success: true };
    } catch (error) {
      console.error('强制注销用户会话失败:', error);
      return { success: false, message: '操作失败' };
    }
  }

  /**
   * 生成会话ID
   * @returns 会话ID
   */
  private generateSessionId(): string {
    return crypto.randomBytes(32).toString('hex');
  }

  /**
   * 验证系统访问权限
   * @param systemCode 系统代码
   * @param secretKey 系统密钥
   * @param origin 来源域名
   * @returns 验证结果
   */
  async verifySystemAccess(systemCode: string, secretKey: string, origin?: string): Promise<{
    valid: boolean;
    system?: ISystemDocument;
    message?: string;
  }> {
    try {
      const system = await this.systemDAO.findByCode(systemCode);
      if (!system) {
        return { valid: false, message: '系统不存在' };
      }

      // 验证密钥
      if (!system.verifySecretKey(secretKey)) {
        return { valid: false, message: '密钥验证失败' };
      }

      // 验证来源域名
      if (origin && !system.isOriginAllowed(origin)) {
        return { valid: false, message: '来源域名不被允许' };
      }

      return {
        valid: true,
        system: system
      };
    } catch (error) {
      console.error('系统访问验证失败:', error);
      return { valid: false, message: '验证失败' };
    }
  }
}

export default AuthService;
